home *** CD-ROM | disk | FTP | other *** search
/ APDL Other Worlds / APDL Other Worlds Collection.iso / SF3000 / Extras / !SFskyedit / c / Utils < prev   
Encoding:
Text File  |  2003-10-16  |  11.3 KB  |  357 lines

  1. /*
  2.  *  SFskyedit - Star Fighter 3000 sky colours editor
  3.  *  Utility functions
  4.  *  Copyright (C) 2001  Chris Bazley
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public Licence as published by
  8.  *  the Free Software Foundation; either version 2 of the Licence, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public Licence for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public Licence
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /* ANSI library files */
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <stdbool.h>
  26. #include <limits.h>
  27.  
  28. /* RISC OS library files */
  29. #include "kernel.h"
  30. #include "toolbox.h"
  31. #include "event.h"
  32. #include "window.h"
  33. #include "wimplib.h"
  34. #include "wimp.h"
  35. #include "gadgets.h"
  36. #include "swis.h"
  37. #include "flex.h"
  38.  
  39. /* My library files */
  40. #include "ViewsMenu.h"
  41. #include "err.h"
  42. #include "msgtrans.h"
  43. #include "hourglass.h"
  44. #include "Macros.h"
  45. #include "SFformats.h"
  46. #include "FilePerc.h"
  47.  
  48. /* Local headers */
  49. #include "Utils.h"
  50. #include "Main.h"
  51.  
  52. #define Wimp_ReportError_UseCategory (1u << 8)
  53. #define Wimp_ReportError_CatInform   (1u << 9)
  54. #define Wimp_ReportError_CatWarning  (2u << 9)
  55. #define Wimp_ReportError_CatProgram  (3u << 9)
  56. #define Wimp_ReportError_CatQuestion (4u << 9)
  57.  
  58. #ifdef INT_COLOUR_FIND
  59. /* OS 2 ColourTrans used R2,G3,B1 and OS 3 ColourTrans uses R2,G4,B1 */
  60. #define RED_WEIGHT   2
  61. #define GREEN_WEIGHT 4
  62. #define BLUE_WEIGHT  1
  63. #define SQUARE(n) ((n)*(n))
  64. #endif
  65.  
  66. /* ----------------------------------------------------------------------- */
  67. /*                         Public functions                                */
  68.  
  69. bool verify_sky_file(SF_SkyColours **sky)
  70. {
  71.   unsigned int *data = (*sky)->shade;
  72.   int numsame, row;
  73.   unsigned int band, oldband;
  74.  
  75.   if(!format_warning)
  76.     return true;
  77.  
  78.   /* 1st row should be 2nd row dithered with itself */
  79.   if(data[0] != data[1])
  80.     goto badfile;
  81.  
  82.   numsame = 1;
  83.   oldband = data[1]; /* kludge as 1st row should be dithered but can't be */
  84.  
  85.   for(row = 2;row < 126;row++) {
  86.     band = data[row];
  87.  
  88.     /* check that 1st = 3rd and 2nd = 4th pixel */
  89.     if((band & 0x000000ff)        != ((band & 0x00ff0000) >> 16)
  90.     || ((band & 0x0000ff00) >> 8) != ((band & 0xff000000) >> 24))
  91.       goto badfile;
  92.  
  93.     /* check that band dithered with previous band */
  94.     if( (band & 0x00ff00ff) != (oldband & 0x00ff00ff)
  95.     &&  (band & 0xff00ff00) != (oldband & 0xff00ff00) )
  96.       goto badfile;
  97.  
  98.     if(band == oldband)
  99.       numsame++;
  100.     else {
  101.       if((oldband & 0xff) != ((oldband & 0xff00) >> 8)) {
  102.         /* check that dithered section was 1 wide */
  103.         if(numsame>1)
  104.           goto badfile;
  105.       }
  106.       else {
  107.         /* check that width of plain section is odd number */
  108.         if((numsame & 1) != 1)
  109.            goto badfile;
  110.       }
  111.       numsame = 1;
  112.     }
  113.     oldband = band;
  114.   }
  115.   return true; /* verified OK */
  116.  
  117. badfile:
  118.   /* Bad format */
  119.   {
  120.     int button;
  121.     WRITE_ERR(shared_err_block, "DithWarn");
  122.  
  123.     if(wimp_version >= 321) {
  124.       /* Nice error box */
  125.       button = wimp_report_error(&shared_err_block, Wimp_ReportError_OK|Wimp_ReportError_Cancel|Wimp_ReportError_UseCategory|Wimp_ReportError_CatInform, taskname, NULL, NULL, msgs_lookup("DithQuiet"));
  126.     }
  127.     else {
  128.       /* Backwards compatibility */
  129.       button = wimp_report_error(&shared_err_block, Wimp_ReportError_OK|Wimp_ReportError_Cancel, taskname);
  130.     }
  131.     switch(button) {
  132.       case 3: /* shut up & continue */
  133.         format_warning = false;
  134.       case Wimp_ReportError_OK: /* continue */
  135.         return true;
  136.     }
  137.   }
  138.   return false;
  139. }
  140.  
  141. /* ----------------------------------------------------------------------- */
  142.  
  143. int absdiff(int a, int b)
  144. {
  145.   int c = a - b;
  146.   if(c < 0)
  147.     return -c;
  148.   return c;
  149. }
  150.  
  151. /* ----------------------------------------------------------------------- */
  152.  
  153. char brightness_of_24bit_col(unsigned int colour)
  154. {
  155.   int r,g,b;
  156.   r = (colour & 0x0000ff00) >> 8;
  157.   g = (colour & 0x00ff0000) >> 16;
  158.   b = (colour & 0xff000000) >> 24;
  159.   /* CIE luminance weights for red, green and blue (0.299, 0.587, 0.114), which is the standard conversion for broadcast television */
  160.  return (char)((int)(0.299*(float)r) + (int)(0.587*(float)g) + (int)(0.114*(float)b));
  161. }
  162.  
  163. /* ----------------------------------------------------------------------- */
  164.  
  165. _kernel_oserror *open_topleftofwin(unsigned int flags, ObjectId showobj, ObjectId relativeto, ObjectId parent, ComponentId parent_component)
  166. {
  167.   WimpGetWindowStateBlock winstate;
  168.   WindowShowObjectBlock showblock;
  169.   THROW(window_get_wimp_handle(0, relativeto, &(winstate.window_handle)))
  170.   THROW(wimp_get_window_state(&winstate))
  171.   showblock.visible_area.xmin = winstate.visible_area.xmin+64;
  172.   showblock.visible_area.ymin = winstate.visible_area.ymax-64;
  173.  
  174.   unsigned int state;
  175.   THROW(toolbox_get_object_state(0, showobj, &state))
  176.   if(FLAG_SET(state, Toolbox_GetObjectState_Showing))
  177.     /* Already open (may be iconised) */
  178.     return ViewsMenu_show_object(flags, showobj, Toolbox_ShowObject_TopLeft, &showblock, parent, parent_component);
  179.   else
  180.     /* Not open (can't very well be iconised!) */
  181.     return toolbox_show_object(flags, showobj, Toolbox_ShowObject_TopLeft, &showblock, parent, parent_component);
  182. }
  183.  
  184. /* ----------------------------------------------------------------------- */
  185.  
  186. _kernel_oserror *show_win_at_ptr(unsigned int flags, ObjectId id, ObjectId parent, ComponentId parent_component)
  187. {
  188.   unsigned int state;
  189.   THROW(toolbox_get_object_state(0, id, &state))
  190.  
  191.   if(FLAG_SET(state, Toolbox_GetObjectState_Showing))
  192.     /* Already open (may be iconised) */
  193.     THROW(ViewsMenu_show_object(flags, id, Toolbox_ShowObject_Default, NULL, parent, parent_component))
  194.   else
  195.     /* Not open (can't very well be iconised!) */
  196.     THROW(toolbox_show_object(flags, id, Toolbox_ShowObject_AtPointer, NULL, parent, parent_component))
  197.  
  198.   return NULL; /* success */
  199. }
  200.  
  201. /* ----------------------------------------------------------------------- */
  202.  
  203. char *tail(char *pathname, int length)
  204. {
  205.   char *ptr;
  206.   int dotcount;
  207.   ptr = (char *)((int)pathname + strlen(pathname)); /* terminator */
  208.   dotcount = 0;
  209.   while(ptr > pathname && dotcount<length) {
  210.     ptr--; /* scan string backwards from terminator */
  211.     if(*ptr == '.')
  212.       dotcount++;
  213.   }
  214.   if(dotcount >= length)
  215.     return (char *)((int)ptr + 1);
  216.   return ptr;
  217. }
  218.  
  219. /* ----------------------------------------------------------------------- */
  220.  
  221. char real_to_mode13col(unsigned int real_col)
  222. {
  223.   /* Find nearest to ideal colour in default mode 13 palette */
  224. #ifdef INT_COLOUR_FIND
  225.   if(use_colour_trans) {
  226. #endif
  227.     int nearest_colour;
  228.     RE(_swix(ColourTrans_ReturnColourNumberForMode, _INR(0,2)|_OUT(0), real_col, 13, 0, &nearest_colour))
  229.     return nearest_colour;
  230. #ifdef INT_COLOUR_FIND
  231.   } else {
  232.     /* Like ColourTrans we use a least squares function,
  233.        but we have control over the weights */
  234.     char best_col;
  235.     unsigned int least_dist = UINT_MAX;
  236.     int target_red = (real_col & 0xff00)>>8;
  237.     int target_green = (real_col & 0xff0000)>>16;
  238.     int target_blue = (real_col & 0xff000000)>>24;
  239.     for(int colnum = 0; colnum <= 255; colnum++) {
  240.       unsigned int dist = RED_WEIGHT*SQUARE(((palette[colnum] & 0xff00)>>8) - target_red)
  241.       + GREEN_WEIGHT*SQUARE(((palette[colnum] & 0xff0000)>>16) - target_green)
  242.       + BLUE_WEIGHT*SQUARE(((palette[colnum] & 0xff000000)>>24) - target_blue);
  243.       if(dist < least_dist) {
  244. #ifndef NDEBUG
  245.         {char string[256];
  246.         sprintf(string, "report new best match (dist %u) is col %d (R=%d, G=%d, B=%d)",dist,colnum,((palette[colnum] & 0xff00)>>8),((palette[colnum] & 0xff0000)>>16),((palette[colnum] & 0xff000000)>>24));
  247.         _kernel_oscli(string);
  248.         }
  249. #endif
  250.         least_dist = dist;
  251.         best_col = colnum;
  252.       }
  253. #ifndef NDEBUG
  254.       else if(dist < least_dist*2) {
  255.         char string[256];
  256.         sprintf(string, "report discounting col %d at dist of %u (R=%d, G=%d, B=%d)",colnum, dist,((palette[colnum] & 0xff00)>>8),((palette[colnum] & 0xff0000)>>16),((palette[colnum] & 0xff000000)>>24));
  257.         _kernel_oscli(string);
  258.       }
  259. #endif
  260.     }
  261.     return best_col;
  262.   }
  263. #endif
  264. }
  265.  
  266. /* ----------------------------------------------------------------------- */
  267.  
  268. _kernel_oserror *setgadgetfaded(ObjectId window, ComponentId gadget, int flagval)
  269. {
  270.   /* Set gadget to shaded/unshaded */
  271.   unsigned int flags;
  272.   THROW(gadget_get_flags(0, window, gadget, &flags))
  273.   return gadget_set_flags(0, window, gadget, (flags & ~Gadget_Faded) | (Gadget_Faded * flagval));
  274. }
  275.  
  276. /* ----------------------------------------------------------------------- */
  277.  
  278. int watch_caret(int event_code, WimpPollBlock *event, IdBlock *id_block, void *handle)
  279. {
  280.   switch(event_code) {
  281.     case Wimp_ELoseCaret:
  282.       *(bool *)handle = false;
  283.       return 1; /* claim event */
  284.  
  285.     case Wimp_EGainCaret:
  286.       *(bool *)handle = true;
  287.       return 1; /* claim event */
  288.  
  289.     default:
  290.       return 0; /* don't handle this event */
  291.   }
  292. }
  293.  
  294. /* ----------------------------------------------------------------------- */
  295.  
  296. int hand_back_caret(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
  297. {
  298.   /* Is our ancestor alive and not hidden? */
  299.   unsigned int anc_state;
  300.   if(toolbox_get_object_state(0, id_block->ancestor_id, &anc_state) == NULL
  301.   && FLAG_SET(anc_state, Toolbox_GetObjectState_Showing)) {
  302.     /* Did we have the input focus? */
  303.     if(*(bool *)handle == true) {
  304.       /* And is there now no input focus anywhere on the desktop? */
  305.       WimpGetCaretPositionBlock now_pos;
  306.       if(!E(wimp_get_caret_position(&now_pos)) && now_pos.window_handle == -1) {
  307.         /* OK, pass the focus back to ancestor window */
  308.         int window;
  309.         if(!E(window_get_wimp_handle(0, id_block->ancestor_id, &window)))
  310.           RE(wimp_set_caret_position(window, -1, 0, 0, -1, -1))
  311.       }
  312.     }
  313.   }
  314.   return 0; /* pass event on */
  315. }
  316.  
  317. /* ----------------------------------------------------------------------- */
  318.  
  319. _kernel_oserror *hide_shared_if_child(ObjectId parent_id, ObjectId shared_id)
  320. {
  321.   ObjectId ancestor;
  322.  
  323.   THROW(toolbox_get_ancestor(0, shared_id, &ancestor, NULL))
  324.   if(ancestor != parent_id)
  325.     return NULL;
  326.   return hide_deiconise(shared_id);
  327. }
  328.  
  329. /* ----------------------------------------------------------------------- */
  330.  
  331. _kernel_oserror *hide_deiconise(ObjectId window)
  332. {
  333.   unsigned int state;
  334.   THROW(toolbox_get_object_state(0, window, &state))
  335.   if(!FLAG_SET(state, Toolbox_GetObjectState_Showing))
  336.     return NULL; /* nothing to do */
  337.  
  338.   THROW(toolbox_hide_object(0, window))
  339.  
  340.   /* Get wimp handle of underlying window */
  341.   WimpMessage msg_block;
  342.   THROW(window_get_wimp_handle(0, window, &msg_block.data.words[0]))
  343.  
  344.   /* Broadcast message &400CB (window closed) in case it was iconised */
  345.   msg_block.hdr.size = sizeof(msg_block.hdr) + sizeof(int);
  346.   msg_block.hdr.your_ref = 0;
  347.   msg_block.hdr.action_code = Wimp_MWindowClosed;
  348.   return wimp_send_message(Wimp_EUserMessage, &msg_block, 0, 0, NULL);
  349. }
  350.  
  351. /* ----------------------------------------------------------------------- */
  352.  
  353. _kernel_oserror *load_compressed(char *filepath, flex_ptr buffer_anchor)
  354. {
  355.   return perc_operation(FILEPERC_OP_DECOMP, filepath, 0, buffer_anchor);
  356. }
  357.